home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / C Internet Config / IC Application Source ƒ / 68k Internet Config ƒ / C Source ƒ / IC Misc Subs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-06  |  16.3 KB  |  855 lines  |  [TEXT/SPM ]

  1. /*
  2.     IC Misc Subs.c
  3.     
  4. */
  5.  
  6. #include <stdarg.h>
  7. #include <Icons.h>
  8.  
  9. #include "IC Globals.h"
  10. #include "IC Misc Subs.h"
  11.  
  12. Str31 typed_chars;
  13. long typed_time;
  14. ListHandle typed_lh;
  15.  
  16. OSErr PrepMem(void){
  17.     long totalSize,contigSize;
  18.     
  19.     PurgeSpace(&totalSize,&contigSize);
  20.     
  21.     // totalSize is the total free space available if purge & compact took place
  22.     // contigSize is largest contiguous block available if purge took place
  23.     
  24.     PurgeMem(contigSize); // purge memory to get the contigSize area
  25.     
  26.     CompactMem(totalSize);
  27.     
  28.     return noErr;
  29. }
  30.  
  31. StringPtr SetPString(StringPtr str,short ct,...){
  32.     str[0]=0;
  33.     
  34.     if (ct)
  35.         vConcat(str,ct,__va(ct));
  36.     
  37.     return str;
  38. }
  39.  
  40. StringPtr Delete(StringPtr str,short start,short end){
  41.     
  42.     // keep values within bounds
  43.     if (start<1)
  44.         start=1;
  45.     
  46.     if (end>255)
  47.         end=255;
  48.     
  49.     if (str==(StringPtr)0)
  50.         return str; // return null string
  51.     
  52.     // if string shorter than start, nothing to delete
  53.     if (str[0]<start)
  54.         return str;
  55.     
  56.     // if string shorter than tail of delete, we're truncating string
  57.     if (str[0]<=end){
  58.         str[0]=start-1;
  59.         return str;
  60.     }
  61.     
  62.     if (start==1){
  63.         // move end down to front, string extends past end
  64.         str[0]-=end;
  65.         BlockMoveData((Ptr)&(str[end+1]),(Ptr)&(str[1]),str[0]);
  66.         return str;
  67.     }
  68.     
  69.     // start & end are in middle of  string
  70.     str[0] -= (end-start+1); // subtract chars being removed
  71.     BlockMoveData((Ptr)&(str[end+1]),(Ptr)&(str[start]),(end-start+1));
  72.     return str;
  73. }
  74.  
  75. StringPtr NewPString(StringPtr str){
  76.     StringPtr s;
  77.     
  78.     s=(StringPtr)NewPtr(256);
  79.     s[0]=0;
  80.     
  81.     if (str!=(StringPtr)0)
  82.         SetPString(s,1,str);
  83.     
  84.     return s;
  85. }
  86.  
  87. StringPtr Concat(StringPtr str,short ct,...){
  88.     return vConcat(str,ct,__va(ct));
  89. }
  90.  
  91. StringPtr vConcat(StringPtr str,short ct,va_list v){
  92.     StringPtr sp;
  93.     unsigned char mv;
  94.     
  95.     if (str==(StringPtr)0)
  96.         return str;
  97.     
  98.     while (ct){
  99.         sp=va_arg(v,StringPtr);
  100.         
  101.         if (sp!=(StringPtr)0){
  102.             mv=sp[0];
  103.             
  104.             if (mv+str[0]>255)
  105.                 mv=255-str[0];
  106.             
  107.             if (mv){
  108.                 BlockMoveData((Ptr)&(sp[1]),(Ptr)&(str[str[0]+1]),mv);
  109.                 str[0]+=mv;
  110.             }
  111.         }
  112.         ct--;
  113.     }
  114.     
  115.     return str;
  116. }
  117.  
  118. void InitMiscSubs(void){
  119.     typed_chars[0]=0;
  120.     typed_time=0;
  121.     typed_lh=(ListHandle)0;
  122. }
  123.  
  124. StringPtr TPCopy(StringPtr to,StringPtr source,short start,short count){
  125.     if (start<1){
  126.         count=count-(1-start);
  127.         start=1;
  128.     }
  129.     
  130.     if (start+count>source[0])
  131.         count=source[0]-start+1;
  132.     
  133.     if (count<0)
  134.         count=0;
  135.     to[0]=count;
  136.     if (count)
  137.         BlockMoveData((Ptr)&(source[start]),&(to[1]),count);
  138.     
  139.     return to;
  140. }
  141.  
  142. short TPPos(StringPtr sub,StringPtr str){
  143.     Handle sh=NewHandle(256);
  144.     long pos;
  145.     
  146.     if (sh==(Handle)0)
  147.         return -1;
  148.     
  149.     HLock(sh);
  150.     
  151.     BlockMoveData(str,*sh,str[0]+1);
  152.     
  153.     pos=Munger(sh,1,&(sub[1]),sub[0],(Ptr)0,0);
  154.     
  155.     HUnlock(sh);
  156.     DisposeHandle(sh);
  157.     
  158.     return pos;
  159. }
  160.  
  161. void StringToOSType(StringPtr s,OSType* otype){
  162.     Str255 ts;
  163.     
  164.     SetPString(ts,2,s,"\p\0\0\0\0");
  165.     BlockMoveData(&(ts[1]),otype,4);
  166. }
  167.  
  168. void OSTypeToString(OSType otype,StringPtr s){
  169.     BlockMoveData(&otype,&(s[1]),4);
  170.     s[0]=4;
  171. }
  172.  
  173. void DrawIcon(short id,Rect* r,Boolean highlighted){
  174.     Handle suite,iconh;
  175.     short transform;
  176.     
  177.     if ((System7)&&(GetIconSuite(&suite,id,svAllLargeData)==noErr)){
  178.         if (highlighted)
  179.             transform=ttSelected;
  180.         else
  181.             transform=ttNone;
  182.         
  183.         PlotIconSuite(r,0,transform,suite);
  184.         DisposeIconSuite(suite,false);
  185.     } else {
  186.         iconh=Get1Resource('ICN#',id);
  187.         if (iconh!=(Handle)0){
  188.             PlotIcon(r,iconh);
  189.             ReleaseResource(iconh);
  190.         }
  191.     }
  192. }
  193.  
  194. OSErr FSWriteQ(short refnum,long count,Ptr buf){
  195.     return FSWrite(refnum,&count,buf);
  196. }
  197.  
  198. OSErr FSReadQ(short refnum,long count,Ptr buf){
  199.     return FSRead(refnum,&count,buf);
  200. }
  201.  
  202. short SelectedLine(ListHandle lh){
  203.     Cell acell;
  204.     
  205.     SetPt(&acell,0,0);
  206.     
  207.     if (LGetSelect(true,&acell,lh))
  208.         return acell.v;
  209.     
  210.     return -1;
  211. }
  212.  
  213. Boolean IsKeyDown(short keycode){
  214.     unsigned char mykeys[16];
  215.     KeyMap* kmp;
  216.     
  217.     kmp=(KeyMap*)&mykeys;
  218.     
  219.     GetKeys(*kmp);
  220.     
  221.     return ((mykeys[keycode>>3]>>(keycode&7))&1);
  222. }
  223.  
  224. OSErr ICGetVolInfo(StringPtr name,short* vrn,short index,long* CrDate){
  225.     ParamBlockRec pb;
  226.     OSErr oe;
  227.     
  228.     if ((name[0]!=0)&&(name[name[0]]!=':'))
  229.         Concat(name,1,"\p:");
  230.     
  231.     pb.volumeParam.ioNamePtr=name;
  232.     pb.volumeParam.ioVRefNum=*vrn;
  233.     pb.volumeParam.ioVolIndex=index;
  234.     
  235.     oe=PBGetVInfoSync(&pb);
  236.     
  237.     if (oe==noErr){
  238.         *CrDate=pb.volumeParam.ioVCrDate;
  239.         *vrn=pb.volumeParam.ioVRefNum;
  240.     }
  241.     
  242.     return oe;
  243. }
  244.  
  245. OSErr MyGetAPPL(OSType sig,FSSpec* fs){
  246.     short i=1;
  247.     DTPBRec pbdt;
  248.     long crdate;
  249.     OSErr oe;
  250.     Boolean found=false;
  251.     
  252.     if (System7){
  253.         do {
  254.             fs->vRefNum=0;
  255.             fs->name[0]=0;
  256.             oe=ICGetVolInfo(fs->name,&(fs->vRefNum),i++,&crdate);
  257.             if (oe==noErr){
  258.                 fs->name[0]=0;
  259.                 pbdt.ioNamePtr=fs->name;
  260.                 pbdt.ioVRefNum=fs->vRefNum;
  261.                 
  262.                 oe=PBDTGetPath(&pbdt);
  263.                 
  264.                 if (oe==noErr){
  265.                     pbdt.ioIndex=0;
  266.                     pbdt.ioFileCreator=sig;
  267.                     
  268.                     oe=PBDTGetAPPLSync(&pbdt);
  269.                     
  270.                     found=(oe==noErr);
  271.                 }
  272.                 oe=noErr;
  273.             }
  274.         } while ((!found)&&(oe==noErr));
  275.     }
  276.     
  277.     if (found){
  278.         oe=noErr;
  279.         fs->parID=pbdt.ioAPPLParID;
  280.     } else {
  281.         oe=afpItemNotFound;
  282.         fs->vRefNum=0;
  283.         fs->parID=2;
  284.         fs->name[0]=0;
  285.     }
  286.     
  287.     return oe;
  288. }
  289.  
  290. OSErr ICFSpGetCatInfo(FSSpec* fs,short index,CInfoPBRec* pb){
  291.     pb->hFileInfo.ioVRefNum=fs->vRefNum;
  292.     pb->hFileInfo.ioDirID=fs->parID;
  293.     pb->hFileInfo.ioNamePtr=fs->name;
  294.     pb->hFileInfo.ioFDirIndex=index;
  295.     
  296.     return PBGetCatInfoSync(pb);
  297. }
  298.  
  299. OSErr ICFSpSetCatInfo(FSSpec* fs,CInfoPBRec* pb){
  300.     pb->hFileInfo.ioVRefNum=fs->vRefNum;
  301.     pb->hFileInfo.ioDirID=fs->parID;
  302.     pb->hFileInfo.ioNamePtr=fs->name;
  303.     
  304.     return PBSetCatInfoSync(pb);
  305. }
  306.  
  307. RgnHandle GetWindowContentRegion(WindowPtr wind){
  308.     return ((WindowPeek)wind)->contRgn;
  309. }
  310.  
  311. RgnHandle GetWindowStructureRegion(WindowPtr wind){
  312.     return ((WindowPeek)wind)->strucRgn;
  313. }
  314.  
  315. Boolean TitleBarOnScreen(WindowPtr wp){
  316.     RgnHandle rgn;
  317.     Boolean ret;
  318.     
  319.     rgn=NewRgn();
  320.     
  321.     CopyRgn(GetWindowStructureRegion(wp),rgn);
  322.     DiffRgn(rgn,GetWindowContentRegion(wp),rgn);
  323.     SectRgn(rgn,GetGrayRgn(),rgn);
  324.     ret=!EmptyRgn(rgn);
  325.     DisposeRgn(rgn);
  326.     
  327.     return ret;
  328. }
  329.  
  330. void GetWindowPortRect(WindowPtr wind,Rect* portRect){
  331.     *portRect=((WindowPeek)wind)->port.portRect;
  332. }
  333.  
  334. void GetWindowRect(WindowPtr wind,Rect* r){
  335.     SetPort(wind);
  336.     GetWindowPortRect(wind,r);
  337.     LocalToGlobal(&(topLeft(*r)));
  338.     LocalToGlobal(&(botRight(*r)));
  339. }
  340.  
  341. void CentreRect(Rect* inside_rect,Rect* res_rect){
  342.     Point stat_siz;
  343.     
  344.     stat_siz=botRight(*inside_rect);
  345.     SubPt(topLeft(*inside_rect),&stat_siz);
  346.     OffsetRect(res_rect,-res_rect->left,-res_rect->top);
  347.     SubPt(botRight(*res_rect),&stat_siz);
  348.     stat_siz.h/=2;
  349.     stat_siz.v/=2;
  350.     AddPt(topLeft(*inside_rect),&stat_siz);
  351.     OffsetRect(res_rect,stat_siz.h,stat_siz.v);
  352. }
  353.  
  354. void CentreAlert(short id){
  355.     AlertTHndl alerth;
  356.     Rect bounds;
  357.     
  358.     alerth=(AlertTHndl)GetResource('ALRT',id);
  359.     if (alerth!=(AlertTHndl)0){
  360.         bounds=qd.screenBits.bounds;
  361.         bounds.bottom=(bounds.bottom-bounds.top)*2/3+bounds.top;
  362.         HLock((Handle)alerth);
  363.         CentreRect(&bounds,&((*alerth)->boundsRect));
  364.         HUnlock((Handle)alerth);
  365.     }
  366. }
  367.  
  368. StringPtr GetAString(StringPtr dest,short id,short index){
  369.     GetIndString(dest,id,index);
  370.     return dest;
  371. }
  372.  
  373. void Assert(Boolean b){
  374.     if (!b)
  375.         DebugStr("\pAssertion failure ; sc");
  376. }
  377.  
  378. void SetItemEnable(MenuHandle mh,short item,Boolean enable){
  379.     if (enable)
  380.         EnableItem(mh,item);
  381.     else
  382.         DisableItem(mh,item);
  383. }
  384.  
  385. Boolean DirtyKey(char ch){
  386.     switch (ch){
  387.         case homeChar: case endChar: case helpChar: case pageUpChar: case pageDownChar:
  388.         case leftArrowChar: case rightArrowChar: case upArrowChar: case downArrowChar:
  389.             return false;
  390.         default:
  391.             return true;
  392.     }
  393. }
  394.  
  395. OSErr IsVolumeWriteable(short vRefNum){
  396.     HParamBlockRec pb;
  397.     OSErr err;
  398.     
  399.     pb.volumeParam.ioVRefNum=vRefNum;
  400.     pb.volumeParam.ioNamePtr=(StringPtr)0;
  401.     pb.volumeParam.ioVolIndex=0;
  402.     
  403.     err=PBHGetVInfoSync(&pb);
  404.     
  405.     if (err==noErr){
  406.         if (pb.volumeParam.ioVAtrb&0x0080)
  407.             err=wPrErr; // volume locked by hardware
  408.         else if (pb.volumeParam.ioVAtrb&0x8000)
  409.             err=fLckdErr; // locked by software
  410.     }
  411.     
  412.     return err;
  413. }
  414.  
  415. OSErr IsFileWriteable(FSSpec* fs){
  416.     CInfoPBRec pb;
  417.     OSErr err;
  418.     
  419.     pb.hFileInfo.ioNamePtr=fs->name;
  420.     pb.hFileInfo.ioVRefNum=fs->vRefNum;
  421.     pb.hFileInfo.ioDirID=fs->parID;
  422.     pb.hFileInfo.ioFDirIndex=0; // use ioNamePtr and ioDirID
  423.     err=PBGetCatInfoSync(&pb);
  424.     
  425.     if (err==noErr)
  426.         if (pb.hFileInfo.ioFlAttrib&0x01)
  427.             err=fLckdErr;
  428.     
  429.     return err;
  430. }
  431.  
  432. OSErr HGetDirAccess(short vRefNum,long dirID,StringPtr name,long* ownerID,long* groupID,long* accessRights){
  433.     HParamBlockRec pb;
  434.     OSErr err;
  435.     
  436.     pb.accessParam.ioNamePtr=name;
  437.     pb.accessParam.ioVRefNum=vRefNum;
  438.     pb.fileParam.ioDirID=dirID; // need to set offset 48
  439.     
  440.     err=PBHGetDirAccessSync(&pb);
  441.     
  442.     *ownerID=pb.accessParam.ioACOwnerID;
  443.     *groupID=pb.accessParam.ioACGroupID;
  444.     *accessRights=pb.accessParam.ioACAccess;
  445.     
  446.     return err;
  447. }
  448.  
  449. Boolean FileLocked(FSSpec* fss){
  450.     Boolean locked;
  451.     long access,junk;
  452.     
  453.     locked=IsVolumeWriteable(fss->vRefNum)!=noErr;
  454.     
  455.     if (!locked)
  456.         locked=IsFileWriteable(fss)!=noErr;
  457.     
  458.     if (!locked){
  459.         if (HGetDirAccess(fss->vRefNum,fss->parID,(StringPtr)0,&junk,&junk,&access)==noErr)
  460.             locked=!(access&(1L<<26));
  461.     }
  462.     
  463.     return locked;
  464. }
  465.  
  466. void LSetNoSelection(ListHandle list){
  467.     Cell c;
  468.     
  469.     c.v=0;
  470.     c.h=0;
  471.     
  472.     while (LGetSelect(true,&c,list)){
  473.         LSetSelect(false,c,list);
  474.         c.v++;
  475.         c.h=0;
  476.     }
  477. }
  478.  
  479. void LSetSingleSelection(ListHandle list,short v){
  480.     Cell c;
  481.     
  482.     c.h=0;
  483.     c.v=v;
  484.     
  485.     LSetNoSelection(list);
  486.     LSetSelect(true,c,list);
  487.     LAutoScroll(list);
  488. }
  489.  
  490. StringPtr LGetUniqueEntryName(ListHandle list,Cell* c,ListKeyUPP getentryname,StringPtr dest){
  491.     Str31 ts;
  492.     
  493.     dest[0]=0;
  494.     
  495.     if (getentryname!=(ListKeyUPP)0)
  496.         CallListKeyProc(getentryname,list,*c,dest);
  497.     
  498.     ts[0]=3;
  499.     ts[1]=0;
  500.     ts[2]=c->v/256;
  501.     ts[3]=c->v%256;
  502.     
  503.     return Concat(dest,1,ts);
  504. }
  505.  
  506. Boolean LGetFirstSelection(ListHandle list,Cell* c,ListKeyUPP getentryname){
  507.     Str255 best,n;
  508.     short index;
  509.     Boolean ret=false;
  510.     
  511.     c->h=c->v=0;
  512.     best[0]=2;
  513.     best[1]=best[2]=255;
  514.     
  515.     while (LGetSelect(true,c,list)){
  516.         ret=true;
  517.         
  518.         if (getentryname!=(ListKeyUPP)0)
  519.             CallListKeyProc(getentryname,list,*c,n);
  520.         else {
  521.             n[0]=2;
  522.             n[1]=n[2]=255;
  523.         }
  524.         
  525.         if (IUCompString(n,best)<0){
  526.             index=c->v;
  527.             SetPString(best,1,n);
  528.         }
  529.         c->v++;
  530.     }
  531.     c->h=0;
  532.     c->v=index;
  533.     
  534.     return ret;
  535. }
  536.  
  537. Boolean LSelectFirstBefore(ListHandle list,const StringPtr s,ListKeyUPP getentryname){
  538.     short i,index=0;
  539.     Cell c;
  540.     Str255 best="\p",n;
  541.     Boolean good=false;
  542.     
  543.     for (i=0;i<(*list)->dataBounds.bottom-1;i++){
  544.         c.h=0;
  545.         c.v=i;
  546.         if (getentryname!=(ListKeyUPP)0)
  547.             CallListKeyProc(getentryname,list,c,n);
  548.         else {
  549.             n[0]=2;
  550.             n[1]=n[2]=255;
  551.         }
  552.         
  553.         if ((IUCompString(s,n)>0)&&(IUCompString(n,best)>0)){
  554.             SetPString(best,1,n);
  555.             index=c.v;
  556.             good=true;
  557.         }
  558.     }
  559.     
  560.     if (good)
  561.         LSetSingleSelection(list,index);
  562.     
  563.     return good;
  564. }
  565.  
  566. Boolean LGetLastSelection(ListHandle list,Cell* c,ListKeyUPP getentryname){
  567.     Str255 n,best="\p";
  568.     short index;
  569.     Boolean ret=false;
  570.     
  571.     c->v=c->h=0;
  572.     
  573.     while (LGetSelect(true,c,list)){
  574.         ret=true;
  575.         if (getentryname!=(ListKeyUPP)0)
  576.             CallListKeyProc(getentryname,list,*c,n);
  577.         else {
  578.             n[0]=2;
  579.             n[1]=n[2]=255;
  580.         }
  581.         
  582.         if (IUCompString(n,best)>0){
  583.             index=c->v;
  584.             SetPString(best,1,n);
  585.         }
  586.         c->v++;
  587.     }
  588.     c->h=0;
  589.     c->v=index;
  590.     
  591.     return ret;
  592. }
  593.  
  594. Boolean LSelectFirstAfter(ListHandle list,const StringPtr s,ListKeyUPP getentryname,Boolean orequal){
  595.     short i,index,compa;
  596.     Cell c;
  597.     Str255 best,n;
  598.     Boolean good=false;
  599.     
  600.     best[0]=2;
  601.     best[1]=best[2]=255;
  602.     
  603.     for (i=0;i<(*list)->dataBounds.bottom-1;i++){
  604.         c.h=0;
  605.         c.v=i;
  606.         if (getentryname!=(ListKeyUPP)0)
  607.             CallListKeyProc(getentryname,list,c,n);
  608.         else {
  609.             n[0]=2;
  610.             n[1]=n[2]=255;
  611.         }
  612.         compa=IUCompString(s,n);
  613.         
  614.         if (((compa<0)||((compa==0)&&orequal))&&(IUCompString(n,best)<0)){
  615.             SetPString(best,1,n);
  616.             index=c.v;
  617.             good=true;
  618.         }
  619.     }
  620.     if (good)
  621.         LSetSingleSelection(list,index);
  622.     
  623.     return good;
  624. }
  625.  
  626. void DoListKey(ListHandle list,EventRecord* er,ListKeyUPP getentryname){
  627.     Cell c;
  628.     short index;
  629.     Boolean dummy,found;
  630.     long curticks=er->when;
  631.     char ch;
  632.     Str255 s;
  633.     
  634.     ch=er->message&0x00ff;
  635.     
  636.     if ((typed_lh!=list)||(ch<' ')){
  637.         typed_time=0;
  638.         typed_lh=list;
  639.     }
  640.     
  641.     switch (ch){
  642.         case downArrowChar:
  643.             c.h=c.v=index=0;
  644.             while (LGetSelect(true,&c,list)){
  645.                 c.v++;
  646.                 index=c.v;
  647.             }
  648.             if (index>(*list)->dataBounds.bottom)
  649.                 index=(*list)->dataBounds.bottom;
  650.             
  651.             LSetSingleSelection(list,index);
  652.             LAutoScroll(list);
  653.             break;
  654.         case upArrowChar:
  655.             c.h=c.v=0;
  656.             if (!LGetSelect(true,&c,list))
  657.                 c.v=(*list)->dataBounds.bottom;
  658.             if (c.v>0)
  659.                 c.v--;
  660.             LSetSingleSelection(list,c.v);
  661.             LAutoScroll(list);
  662.             break;
  663.         case homeChar:
  664.             LScroll(0,-(*list)->dataBounds.bottom,list);
  665.             break;
  666.         case endChar:
  667.             LScroll(0,(*list)->dataBounds.bottom,list);
  668.             break;
  669.         case pageUpChar:
  670.             LScroll(0,-((*list)->visible.bottom-(*list)->visible.top-2),list);
  671.             break;
  672.         case pageDownChar:
  673.             LScroll(0,((*list)->visible.bottom-(*list)->visible.top-2),list);
  674.             break;
  675.         case tabChar:
  676.             if (er->modifiers&shiftKey){
  677.                 found=false;
  678.                 if (LGetFirstSelection(list,&c,getentryname)){
  679.                     if (getentryname!=(ListKeyUPP)0)
  680.                         CallListKeyProc(getentryname,list,c,s);
  681.                     if (LSelectFirstBefore(list,s,getentryname))
  682.                         found=true;
  683.                 }
  684.                 if (!found)
  685.                     if ((!LGetLastSelection(list,&c,getentryname))||(!LSelectFirstAfter(list,LGetUniqueEntryName(list,&c,getentryname,s),getentryname,false))){
  686.                         LSelectFirstAfter(list,"\p",getentryname,false);
  687.                     }
  688.             }
  689.             break;
  690.         default:
  691.             if (ch>' '){
  692.                 if (curticks-typed_time>60)
  693.                     typed_chars[0]=0;
  694.                 typed_time=curticks;
  695.                 typed_chars[0]++;
  696.                 typed_chars[typed_chars[0]]=ch;
  697.                 if (!LSelectFirstAfter(list,typed_chars,getentryname,true)){
  698.                     Str31 t;
  699.                     t[0]=1;
  700.                     t[1]=255;
  701.                     LSelectFirstBefore(list,t,getentryname);
  702.                 }
  703.             }
  704.             break;
  705.     }
  706. }
  707.  
  708. StringPtr DecStr(long l,StringPtr s){
  709.     NumToString(l,s);
  710.     return s;
  711. }
  712.  
  713. StringPtr VersionStr(long lver,StringPtr s){
  714.     NumVersion ver;
  715.     Str255 tmp;
  716.     long maj;
  717.     
  718.     s[0]=0;
  719.     *((long*)&ver)=lver;
  720.     
  721.     if (ver.majorRev<=9)
  722.         maj=ver.majorRev;
  723.     else {
  724.         maj=(ver.majorRev >> 4)&0x0f;
  725.         maj*=10;
  726.         maj+=(ver.majorRev&0x0f);
  727.     }
  728.     DecStr(maj,s);Concat(s,1,"\p.");
  729.     
  730.     maj=(ver.minorAndBugRev>>4)&0x0f;
  731.     Concat(s,2,DecStr(maj,tmp),"\p.");
  732.     
  733.     maj=(ver.minorAndBugRev&0x0f);
  734.     Concat(s,1,DecStr(maj,tmp));
  735.     
  736.     // now the stage
  737.     if (ver.stage&0x20)
  738.         Concat(s,1,"\pd");
  739.     else if (ver.stage&0x40)
  740.         Concat(s,1,"\pa");
  741.     else if (ver.stage&0x60)
  742.         Concat(s,1,"\pb");
  743.     else if (ver.stage&0x80)
  744.         Concat(s,1,"\pr");
  745.     else
  746.         Concat(s,1,"\px");
  747.     
  748.     maj=ver.nonRelRev;
  749.     return Concat(s,1,DecStr(maj,tmp));
  750. }
  751.  
  752. OSErr GetDirName(FSSpec* fs){
  753.     CInfoPBRec pb;
  754.     
  755.     pb.hFileInfo.ioNamePtr=fs->name;
  756.     pb.hFileInfo.ioVRefNum=fs->vRefNum;
  757.     pb.hFileInfo.ioDirID=fs->parID;
  758.     pb.hFileInfo.ioFDirIndex=-1;// get information about ioDirID;
  759.     return PBGetCatInfoSync(&pb);
  760. }
  761.  
  762. OSErr CopyFork(short srn,short drn,long len){
  763.     OSErr err=noErr;
  764.     Ptr p=(Ptr)0;
  765.     long size=65536,count;
  766.     
  767.     do {
  768.         p=NewPtr(size);
  769.         if (p!=(Ptr)0)
  770.             size/=2;
  771.     } while ((p==(Ptr)0)&&(size>=512));
  772.     
  773.     if (p==(Ptr)0)
  774.         err=memFullErr;
  775.     
  776.     while ((err==noErr)&&(len>0)){
  777.         count=size;
  778.         if (count>len)
  779.             count=len;
  780.         
  781.         err=FSRead(srn,&count,p);
  782.         if ((err==noErr)&&(count==0))
  783.             err=eofErr;
  784.         if (err==noErr){
  785.             len -= count;
  786.             err=FSWrite(drn,&count,p);
  787.         }
  788.     }
  789.     
  790.     if (p!=(Ptr)0)
  791.         DisposePtr(p);
  792.     
  793.     return err;
  794. }
  795.  
  796. OSErr CopyFile(FSSpec* source,FSSpec* dest){
  797.     OSErr err,oerr;
  798.     CInfoPBRec pb;
  799.     short srrn,sdrn,drrn,ddrn;
  800.     
  801.     HDelete(dest->vRefNum,dest->parID,dest->name);
  802.     if ((err=ICFSpGetCatInfo(source,0,&pb))==noErr){
  803.         if ((err=HCreate(dest->vRefNum,dest->parID,dest->name,pb.hFileInfo.ioFlFndrInfo.fdCreator,pb.hFileInfo.ioFlFndrInfo.fdType))==noErr){
  804.             if ((err=HOpen(dest->vRefNum,dest->parID,dest->name,fsWrPerm,&ddrn))==noErr){
  805.                 if ((err=HOpenRF(dest->vRefNum,dest->parID,dest->name,fsWrPerm,&drrn))==noErr){
  806.                     if ((err=HOpen(source->vRefNum,source->parID,source->name,fsRdPerm,&sdrn))==noErr){
  807.                         if ((err=HOpenRF(source->vRefNum,source->parID,source->name,fsRdPerm,&srrn))==noErr){
  808.                             if ((err=CopyFork(sdrn,ddrn,pb.hFileInfo.ioFlLgLen))==noErr){
  809.                                 if ((err=CopyFork(srrn,drrn,pb.hFileInfo.ioFlRLgLen))==noErr){
  810.                                     // if no error copy complete
  811.                                 }
  812.                             }
  813.                             FSClose(srrn);
  814.                         }
  815.                         FSClose(sdrn);
  816.                     }
  817.                     FSClose(drrn);
  818.                 }
  819.                 FSClose(ddrn);
  820.             }
  821.         }
  822.     }
  823.     
  824.     if (err==noErr)
  825.         err=ICFSpSetCatInfo(dest,&pb);
  826.     if (err!=noErr)
  827.         HDelete(dest->vRefNum,dest->parID,dest->name);
  828.     
  829.     return err;
  830. }
  831.  
  832. StringPtr GetName(short id1,short id2,StringPtr name){
  833.     StringHandle sh;
  834.     
  835.     sh=GetString(id1);
  836.     if (sh==(StringHandle)0)
  837.         sh=GetString(id2);
  838.     
  839.     if (sh==(StringHandle)0)
  840.         SetPString(name,1,"\punnamed");
  841.     else
  842.         SetPString(name,1,*sh); // don't release the string handle, someone else may be using it
  843.     
  844.     return name;
  845. }
  846.  
  847. StringPtr GetOwnerName(StringPtr name){
  848.     return GetName(owner_id,machine_id,name);
  849. }
  850.  
  851. StringPtr GetMachineName(StringPtr name){
  852.     return GetName(machine_id,owner_id,name);
  853. }
  854.  
  855.